//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<XButton.cpp>
///	@path	~/src/gui/xgui/
///	@date	2008/10/30
///	@brief	.

#define _FULLAPI
#include "config/config.h"

#include "gui/IGuiForm.h"
#include "gui/xgui/XButton.h"
#include "gui/composite/composition.h"
#include "gui/image/ImageResource.h"

namespace xeres {

	IMPL_IOBJECT_CLASS_DYNAMIC( XButton );

	// XButton
	XButton::XButton( void )
		: IGuiControl( Rect<int>() , true , true , true )
		, m_clicked( false )
	{
		GetStyle()->m_horizontal = PlacementStyle::MIDDLE;
		GetStyle()->m_vertical = PlacementStyle::CENTER;
	}

	// XButton
	XButton::XButton( const WString& label , const Rect<int>& placement , function<void()> click )
		: IGuiControl( placement , true , true , true )
		, m_label( label )
		, m_clicked( false )
		, m_onClick( click )
	{
		GetStyle()->m_horizontal = PlacementStyle::MIDDLE;
		GetStyle()->m_vertical = PlacementStyle::CENTER;
	}
	// ~XButton
	XButton::~XButton( void )
	{

	}
	// SetText
	void XButton::SetText( const WString& text )
	{
		m_label.SetString( text );
		UpdateControl();
	}
	// GetStyle
	RefWeak<CTextStyle> XButton::GetStyle( void )
	{
		return m_label.GetStyle();
	}
	// OnKeyInput
	HandleInput XButton::OnKeyInput( Updater& updater )
	{
		return INPUT_UNHANDLED;
	}
	// OnMouseInput
	HandleInput XButton::OnMouseInput( Updater& updater )
	{
		if( !GetEnable() || !GetVisible() )
			return INPUT_UNHANDLED;

		Pair<int> point = updater.GetPoint();
		if( HitTest( point ) )
		{
			if( updater.GetInput().GetAction() == Input::ACTION_MOUSE_LB_CLICK )
			{
				m_clicked  = true;
				return INPUT_HANDLED;
			}
			else if( updater.GetInput().GetAction() == Input::ACTION_MOUSE_LB_UP )
			{
				if( m_clicked && m_onClick != NULL )
					m_onClick();
				m_clicked = false;
				return INPUT_HANDLED;
			}
		}
		return INPUT_UNHANDLED;
	}
	// Draw
	void XButton::Draw( Composition& composition )
	{
		Rect<int> rect( GetBound() );

		if( m_hover )
		{
			Gdiplus::SolidBrush brush( Gdiplus::Color(33,33,33) );
			composition.graphics().FillRectangle( &brush , rect.left() , rect.top() , rect.width() , rect.height() );
		}
		else
		{
			Gdiplus::SolidBrush brush( Gdiplus::Color(110,110,110) );
			composition.graphics().FillRectangle( &brush , rect.left() , rect.top() , rect.width() , rect.height() );
		}

		// Draw text.
		m_label.DrawText( composition , GetRect() , GetBound() );
		
		return;
	}
	
	IMPL_IOBJECT_CLASS_DYNAMIC( XSimpleButton );

	// XSimpleButton
	XSimpleButton::XSimpleButton( void )
		: IGuiControl( Rect<int>() , true , true , true )
		, m_clicked( false )
	{
		GetStyle()->m_horizontal = PlacementStyle::MIDDLE;
		GetStyle()->m_vertical = PlacementStyle::CENTER;
	}

	// XSimpleButton
	XSimpleButton::XSimpleButton( const WString& label , RefWeak<IBitmap> image , const Pair<int>& pos )
		: IGuiControl( make_rect<int>( pos.x , pos.y , 100 , 20 ) , true , true , false )
		, m_text( label )
		, m_clicked( false )
	{
		GetStyle()->m_horizontal = PlacementStyle::MIDDLE;
		GetStyle()->m_vertical = PlacementStyle::CENTER;
		SetImage( image );
	}

	// ~XSimpleButton
	XSimpleButton::~XSimpleButton( void )
	{
	}

	// SetText
	void XSimpleButton::SetText( const WString& text )
	{
		m_text.SetString( text );
		UpdateControl();
	}
	// GetStyle
	RefWeak<CTextStyle> XSimpleButton::GetStyle( void )
	{
		return m_text.GetStyle();
	}
	// SetSize
	bool XSimpleButton::SetSize( const Pair<int>& size )
	{
		TRACE_ERROR( _S("XSimpleButton::SetSize: Button size is determine by image.") );
		return false;
	}
	// GetImage
	RefWeak<IBitmap> XSimpleButton::GetImage( void )
	{
		return m_image;
	}
	// OnKeyInput
	HandleInput XSimpleButton::OnKeyInput( Updater& updater )
	{
		if( !GetEnable() || !GetVisible() || !GetFocus() )
			return INPUT_UNHANDLED;

		if( updater.GetKeyInput().GetKey() == KeyInput::KEY_RETURN )
		{
			if( m_onDefault && m_onDefault( true ) )
				return INPUT_HANDLED;
		}
		else if( updater.GetKeyInput().GetKey() == KeyInput::KEY_ESCAPE )
		{
			if( m_onDefault && m_onDefault( false ) )
				return INPUT_HANDLED;
		}
		return INPUT_UNHANDLED;
	}
	// OnMouseInput
	HandleInput XSimpleButton::OnMouseInput( Updater& updater )
	{
		if( !GetEnable() || !GetVisible() )
			return INPUT_UNHANDLED;

		Pair<int> point = updater.GetPoint();
		if( HitTest( point ) )
		{
			if( updater.GetInput().GetAction() == Input::ACTION_MOUSE_LB_CLICK )
			{
				m_clicked  = true;
				UpdateControl();
				return INPUT_HANDLED;
			}
			else if( updater.GetInput().GetAction() == Input::ACTION_MOUSE_LB_UP )
			{
				if( m_clicked && m_onClick )
					m_onClick();
				m_clicked = false;
				UpdateControl();
				return INPUT_HANDLED;
			}
		}
		return INPUT_UNHANDLED;
	}
	// Draw
	void XSimpleButton::Draw( Composition& composition )
	{
		if( !GetVisible() || m_image.IsNull() )
			return;

		int frame = 0;
		if( m_image->GetFrame() == 4 )
		{
			if( !GetEnable() )
			{
				frame = 3;
			}
			else if( m_clicked )
			{
				frame = 2;
			}
			else if( m_hover )
			{
				frame = 1;
			}
		}

		Rect<int> rect( GetRect() );
		composition.painter().DrawBitmap( m_image , rect.get_min() , rect , 255 , frame );

		if( m_hover && !m_clicked )
			rect.offset( Pair<int>( 0 , -1 ) );

		// Draw text.
		m_text.DrawText( composition , rect , GetBound() );
	}

	// HitTest
	bool XSimpleButton::HitTest( const Pair<int>& pt )
	{
		if( !__super::HitTest( pt ) )
			return false;

		Pair<int> pos = pt - GetPosition();
		
		if( m_image.IsValid() )
		{
			if( pos.x < 0 || pos.x >= (int)m_image->GetWidth() || pos.y < 0 || pos.y >= (int)m_image->GetHeight() )
				return false;
			return m_image->GetPixel( pos ).a > 0;
		}
		else
		{
			return GetPlacement().is_inside( pt );
		}
	}

	// SetImage
	void XSimpleButton::SetImage( RefWeak<IBitmap> image )
	{
		m_image = image;
		if( image.IsValid() )
		{
			__super::SetSize( image->GetSize() );
		}
		UpdateControl();
	}
	// OnClose
	void XSimpleButton::OnClose( void )
	{
		m_onClick = m_onHover = NULL;
		m_onDefault = NULL;
	}
	// OnMouseHover
	void XSimpleButton::OnMouseHover( Updater& updater )
	{
		if( m_onHover )
			m_onHover();
	}

	IMPL_IOBJECT_CLASS_DYNAMIC( XClickButton );

	// XClickButton
	XClickButton::XClickButton( void )
		: GuiSyleComp( new CGuiStyle )
	{
		m_text.SetStyle( Ref<CTextStyle>( m_guiStyle ) );
	}
	// XClickButton
	XClickButton::XClickButton( const WString& label , RefWeak<IBitmap> image , const Pair<int>& pos )
		: XSimpleButton( label , image , pos )
		, GuiSyleComp( new CGuiStyle )
	{
		m_text.SetStyle( Ref<CTextStyle>( m_guiStyle ) );
	}
	// ~XClickButton
	XClickButton::~XClickButton( void )
	{
	}
	// GetStyle
	RefWeak<CGuiStyle> XClickButton::GetStyle( void )
	{
		return m_guiStyle;
	}
	// SetSize
	bool XClickButton::SetSize( const Pair<int>& size )
	{
		if( m_image.IsValid() )
		{
			TRACE_ERROR( _S("XClickButton::SetSize: Image has been set , button size is determine by image.") );
			return false;
		}
		return IGuiControl::SetSize( size );
	}
	// OnKeyInput
	HandleInput XClickButton::OnKeyInput( Updater& updater )
	{
		HandleInput result = __super::OnKeyInput( updater );
		if( result == INPUT_HANDLED )
			ChangeStyle();
		return result;
	}
	// OnMouseInput
	HandleInput XClickButton::OnMouseInput( Updater& updater )
	{
		HandleInput result = __super::OnMouseInput( updater );
		if( result == INPUT_HANDLED )
			ChangeStyle();
		return result;
	}
	// OnEnable
	void XClickButton::OnEnable( bool enable )
	{
		__super::OnEnable( enable );
		ChangeStyle();
	}
	// OnFocus
	void XClickButton::OnFocus( bool focusing )
	{
		__super::OnEnable( focusing );
		if( !focusing )
			m_clicked = false;
		ChangeStyle();
	}
	// OnMouseOver
	void XClickButton::OnMouseOver( bool hovering )
	{
		__super::OnMouseOver( hovering );
		if( !hovering )
			m_clicked = false;
		ChangeStyle();
	}
	// ChangeStyle
	void XClickButton::ChangeStyle( void )
	{
		ResetStyle( m_enable , m_clicked , m_hover , m_focus );
		m_text.SetStyle( Ref<CTextStyle>( m_activeGuiStyle ) );
	}
	// Draw
	void XClickButton::Draw( Composition& composition )
	{
		if( !GetVisible() )
			return;

		Rect<int> rect( GetRect() );

		if( m_image.IsValid() )
		{
			// draw image with image style
			int frame = 0;
			if( m_image->GetFrame() == 4 )
			{
				if( !GetEnable() )
				{
					frame = 3;
				}
				else if( m_clicked )
				{
					frame = 2;
				}
				else if( m_hover )
				{
					frame = 1;
				}
			}
			composition.painter().DrawBitmap( m_image , rect.get_min() , rect , 255 , frame );
		}
		else
		{
			// draw image with background color.
			
			ARGB color = m_activeGuiStyle->m_guiBackgroundColor;
			if( color.a > 0 )
			{
				composition.graphics().FillRectangle(
					&Gdiplus::SolidBrush( Gdiplus::Color( color.a , color.r, color.g , color.b ) ) ,
					toRect( rect ) );
			}
		}

		// Draw text.
		m_text.DrawText( composition , rect , GetBound() );

		// Border of gui.
		if( m_activeGuiStyle->m_guiBorderColor.a > 0 )
		{
			composition.graphics().DrawRectangle(
				&Gdiplus::Pen( m_activeGuiStyle->m_guiBorderColor.argb ) ,
				toRect( GetRect() ) );
		}
	}
	
	
} // namespace xeres
